﻿using System;
using System.Collections.Generic;
using NUnit.Framework;
using ValidationFramework.Extensions;
using ValidationFramework.Reflection;
namespace ValidationFramework.Tests.Extensions
{
    class TypeExtensions
    {
        [TestFixture]
        public class IsExplicitPropertyTests
        {
            #region Test Model

            public class ExplicitImplmentor : IChildInterface
            {
                int IChildInterface.ReadWriteProperty { get; set; }

                int IChildInterface.WriteOnlyProperty
                {
                    set
                    {
                        var test = value;
                    }
                }

                int IChildInterface.ReadOnlyProperty
                {
                    get
                    {
                        return 0;
                    }
                }

                int IChildInterface.ParentInterfaceProperty { get; set; }

                int IParentInterface.ParentInterfaceProperty { get; set; }
            }

            public class ImplicitImplementor : IChildInterface
            {
                public int ReadWriteProperty { get; set; }

                public int ReadOnlyProperty { get; set; }

                public int WriteOnlyProperty { get; set; }

                public int ParentInterfaceProperty { get; set; }
            }

            public interface IChildInterface : IParentInterface
            {
                int ReadWriteProperty { get; set; }

                int ReadOnlyProperty { get; }

                int WriteOnlyProperty { set; }

                int ParentInterfaceProperty { get; set; }
            }

            public interface IParentInterface
            {
                int ParentInterfaceProperty { get; set; }
            }

            public interface IUnrelatedInterface
            {
                int UnrelatedProperty { get; set; }
            }
            #endregion

            [Test]
            public void Should_Return_False_When_Child_Interface_Is_Tested_Against_Parent_Interface()
            {
                Assert.IsFalse(typeof(IChildInterface).IsExplicitProperty("ReadWriteProperty", typeof(IParentInterface)));
            }
            [Test]
            public void Should_Return_True_When_Property_Explicitly_Implmements_An_Interface()
            {
                Assert.IsTrue(typeof(ExplicitImplmentor).IsExplicitProperty("ReadWriteProperty"));
                Assert.IsTrue(typeof(ExplicitImplmentor).IsExplicitProperty("WriteOnlyProperty"));
                Assert.IsTrue(typeof(ExplicitImplmentor).IsExplicitProperty("ReadOnlyProperty"));
                Assert.IsTrue(typeof(ExplicitImplmentor).IsExplicitProperty("ParentInterfaceProperty"));
                Assert.IsTrue(typeof(ExplicitImplmentor).IsExplicitProperty("ParentInterfaceProperty"));
            }
            [Test]
            public void Should_Return_False_When_Property_Implicitly_Implements_An_Interface()
            {
                Assert.IsFalse(typeof(ImplicitImplementor).IsExplicitProperty("ReadWriteProperty"));
                Assert.IsFalse(typeof(ImplicitImplementor).IsExplicitProperty("WriteOnlyProperty"));
                Assert.IsFalse(typeof(ImplicitImplementor).IsExplicitProperty("ReadOnlyProperty"));
                Assert.IsFalse(typeof(ImplicitImplementor).IsExplicitProperty("ParentInterfaceProperty"));
            }
            [Test]
            public void Should_Return_False_When_Type_Not_Implementing_Property()
            {
                Assert.IsFalse(typeof(ExplicitImplmentor).IsExplicitProperty("NotARealProperty"));
            }
            [Test]
            public void Should_Return_False_When_Type_Not_Implementing_Interface()
            {
                Assert.IsFalse(typeof(ImplicitImplementor).IsExplicitProperty("UnrelatedProperty"));
                Assert.IsFalse(typeof(ExplicitImplmentor).IsExplicitProperty("UnrelatedProperty"));
            }
        }

        [TestFixture]
        public class IsNullableTests
        {
            [Test]
            public void Should_Return_True_When_Type_Is_Nullable_Generic()
            {
                Assert.IsTrue(typeof(Nullable<int>).IsNullable());
            }
            [Test]
            public void Should_Return_False_When_Generic_Type_Is_Nullable()
            {
                Assert.IsFalse(typeof(List<Nullable<int>>).IsNullable());
            }
        }
    }
}
